﻿
using NB.MGJ.Common;
using NB.MGJ.Model;
using NB.MGJ.Model.WX;
using NB.MGJ.Service.Config;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using WebAppModel;
using WxPayAPI;

namespace NB.MGJ.WebWap.Controllers
{
    public class WXPortController : Controller
    {
        JsApiPay jsApiPay = new JsApiPay();
     
        //
        // GET: /Home/

        public ActionResult Index()
        {
            if (Session["openid"] == null)
            {
                try
                {
                    //调用【网页授权获取用户信息】接口获取用户的openid和access_token
                    jsApiPay.GetOpenidAndAccessToken();
                }
                catch //(Exception ex)
                {
                    //Response.Write(ex.ToString());
                    //throw;
                }
            }
            return View();
        }

        /// <summary>
        /// 获取code
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult getCode()
        {
            object objResult = "";
            if (Session["url"] != null)
            {
                objResult = Session["url"].ToString();
            }
            else
            {
                objResult = "url为空。";
            }
            return Json(objResult);
        }


        /// <summary>
        /// 通过code换取网页授权access_token和openid的返回数据
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public ActionResult GetWxInfo()
        {
            object objResult = "";
            string strCode = Request.Form["code"];
            if (Session["access_token"] == null || Session["openid"] == null)
            {
                jsApiPay.GetOpenidAndAccessTokenFromCode(strCode);
            }
            string strAccess_Token = Session["access_token"].ToString();
            string strOpenid = Session["openid"].ToString();
            objResult = new { openid = strOpenid, access_token = strAccess_Token };
            return Json(objResult);
        }

  
        /// <summary>
        /// 发红包接口  公众号方式发送
        /// </summary>
        /// <param name="openid">用户的Openid</param>
        /// <param name="cost">金额</param>
        /// <returns></returns>
        [HttpPost]
        //public string SendRedPacket(string openid, decimal cost)
        //{
        //    try
        //    {
        //    string strData = GetJsApiParameters(openid, cost);
        //    string strUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";//这个就是发送红包的API接口了
        //    //string strResult = WxRedPackPost(strUrl, strData);
        //    return strResult;
        //    }
        //    catch (Exception ex)
        //    {
        //        Common.WeiXinHelper.WriteLog("发红包接口err", ex.ToString());
        //        return ex.ToString();
        //    }
        //}

        /// <summary>
        /// 发红包   企业支付到领取  企业支付接口
        /// </summary>
        /// <param name="openid">用户的Openid</param>
        /// <param name="cost">金额</param>
        /// <returns></returns>
        public string EnterprisePayUser(string openid, decimal cost, config_WX wxConfigMolde) 
        {
            try
            {
            string strData = GetPayUserParameters(openid, cost, wxConfigMolde);
            string strUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";//这个就是发送红包的API接口了
      
            string strResult = WxRedPackPost(strUrl, strData,wxConfigMolde.CredentialAddress);
            return strResult;
             }
            catch (Exception ex)
            {
                Common.WeiXinHelper.WriteLog("EnterprisePayUser企业支付接口err", ex.ToString());
                return ex.ToString();
            }
        }

        /// <summary>
        ///关注公众号事件推送 
        /// </summary>
        /// <returns></returns>
        public string GetPushUserEvent(string openid)
        {
            try
            {
            string strData = GetPushParameters(openid);   
            string strUrl = "http://site.openweixin.cn/shnb/wx/";
            string strResult = WxRedPackPost(strUrl, strData, "E:/NewMGJ/Content/cert/上海诺标信息技术有限公司apiclient_cert.p12");
            return strResult;
            }
            catch (Exception ex)
            {
                Common.WeiXinHelper.WriteLog("GetPushUserEvent关注公众号事件推送err", ex.ToString());
                return ex.ToString();
            }
        }


        /***
 * 获取acess_token 
 * 来源www.vxzsk.com
 * @return
 */
        /// <summary>  
        /// 获取AccessToken  
        /// </summary>  
        /// <returns></returns>  
        public JObject GetAccessToken(string appid, string secret)
        {

            string grant_type = "client_credential";
            string tokenUrl = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type={0}&appid={1}&secret={2}", grant_type, appid, secret);
            var wc = new WebClient();
            var strReturn = wc.DownloadString(tokenUrl);
            return JObject.Parse( strReturn);
        }
        public JObject GetJsapi_ticket(string accesstoken)
        {
                    
            string jsapi_ticket = string.Empty;
            string getUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={0}&type=jsapi";
            getUrl = string.Format(getUrl, accesstoken);

            var wc = new WebClient();
            var strReturn = wc.DownloadString(getUrl); //取得微信返回的json数据  
            return JObject.Parse(strReturn);
        }

        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public   string GetTimestamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

       
        #region 生成随机字符串nonceStr
        ///<summary>
        ///生成随机字符串nonceStr
        ///</summary>
        ///<param name="length">目标字符串的长度</param>
        ///<param name="useNum">是否包含数字，1=包含，默认为包含</param>
        ///<param name="useLow">是否包含小写字母，1=包含，默认为包含</param>
        ///<param name="useUpp">是否包含大写字母，1=包含，默认为包含</param>
        ///<param name="useSpe">是否包含特殊字符，1=包含，默认为不包含</param>
        ///<param name="custom">要包含的自定义字符，直接输入要包含的字符列表</param>
        ///<returns>指定长度的随机字符串</returns>
        public string GetRnd(int length, bool useNum, bool useLow, bool useUpp, bool useSpe, string custom)
        {
            byte[] b = new byte[4];
            new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(b);
            Random r = new Random(BitConverter.ToInt32(b, 0));
            string s = null, str = custom;
            if (useNum == true) { str += "0123456789"; }
            if (useLow == true) { str += "abcdefghijklmnopqrstuvwxyz"; }
            if (useUpp == true) { str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; }
            if (useSpe == true) { str += "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; }
            for (int i = 0; i < length; i++)
            {
                s += str.Substring(r.Next(0, str.Length - 1), 1);
            }
            return s;
        }
        #endregion
        public   string SHA1(string str)
        {
            byte[] cleanBytes = Encoding.Default.GetBytes(str);
            byte[] hashedBytes = System.Security.Cryptography.SHA1.Create().ComputeHash(cleanBytes);
            return BitConverter.ToString(hashedBytes).Replace("-", "");
        }

        /// <summary>
        /// 构造参数
        /// </summary>
        /// <returns></returns>
        public string GetJsApiParameters(string openid, decimal cost)
        {
            config_WX model = (Session["wxConfig"] as config_WX);
            int iMin = 1000;
            int iMax = 9999;
            Random rd = new Random();//构造随机数
            string strMch_billno = WxPayConfig.MCHID + DateTime.Now.ToString("yyyyMMddHHmmss") + rd.Next(iMin, iMax).ToString();
            WxPayData jsApiParam = new WxPayData();
            jsApiParam.SetValue("act_name", "活动名称：功能测试");//活动名称
            jsApiParam.SetValue("client_ip", "192.168.1.216");//这里填写的是我本机的内网ip，实际应用不知道需不需要改。
            jsApiParam.SetValue("mch_billno", strMch_billno);//商户订单号,商户订单号（每个订单号必须唯一）组成：mch_id+yyyymmdd+10位一天内不能重复的数字。 接口根据商户订单号支持重入，如出现超时可再调用。
            jsApiParam.SetValue("mch_id", model.mchid);//商户号,微信支付分配的商户号
            jsApiParam.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串，不长于32位
            jsApiParam.SetValue("remark", "备注信息，Dy");//备注信息
            jsApiParam.SetValue("re_openid", openid);//接收者的openid
            jsApiParam.SetValue("send_name", "上海诺标");//商户名称,红包发送者名称
            jsApiParam.SetValue("total_amount", Convert.ToInt32( cost * 100));//红包金额，单位分
            jsApiParam.SetValue("total_num", 1);//红包发放总人数
            jsApiParam.SetValue("wishing", "诺标的测试红包！ 别贪太多哦！ 公众号没钱了.....");//红包祝福语
            jsApiParam.SetValue("wxappid", model.AppId);//公众账号appid,微信分配的公众账号ID（企业号corpid即为此appId）。接口传入的所有appid应该为公众号的appid（在mp.weixin.qq.com申请的），不能为APP的appid（在open.weixin.qq.com申请的）。
            jsApiParam.SetValue("sign", jsApiParam.MakeSign());//签名,切记，这个签名参数必须放在最后，因为他生成的签名，跟前面的参数有关系
            string parameters = jsApiParam.ToXml();
            return parameters;
        }


        public static string getTimestamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        public static string getNoncestr()
        {
            Random random = new Random();
            return MD5Manager.Gen_MD5(random.Next(1000).ToString());
        }
        

        /// <summary>
        /// 获取用户的位置 
        /// </summary>
        /// <returns></returns>
        public string GetUserAddressParameters(string appid, string appsecret) 
        {
            try
            {
                string ticket = GetTicket(appid, appsecret);
                var timeStamp = getTimestamp();
                var nonceStr = getNoncestr();
                WxPayData jsApiParam = new WxPayData();
                jsApiParam.SetValue("jsapi_ticket", ticket);
                jsApiParam.SetValue("noncestr", nonceStr);
                jsApiParam.SetValue("timestamp", timeStamp);//随机字符串，不长于32位
                jsApiParam.SetValue("url", "http://mp.weixin.qq.com?params=value");
                jsApiParam.SetValue("sign", jsApiParam.MakeSign());//签名,切记，这个签名参数必须放在最后，因为他生成的签名，跟前面的参数有关系
                string parameters = jsApiParam.ToXml();
                return parameters;
            }
            catch (Exception ex)
            {
                WeiXinHelper.WriteLog("GetUserAddressParameters错误",ex.ToString());
                throw;
            }
   
        }

 
 
        #region w微信JS-SDK权限签名
        public string GetTicket(string appid, string appsecret)
        {
            try
            {
           #region 通过 appid + appsecert 获取公众号的 access_token（不是用户的 access_token）
           string apiurl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" +appid + "&secret=" +  appsecret;
           #region 通过传入的参数得到url请求
           WebRequest request = WebRequest.Create(@apiurl);
           request.Method = "POST";
           WebResponse response = request.GetResponse();
           Stream stream = response.GetResponseStream();
           Encoding encode = Encoding.UTF8;
           StreamReader reader = new StreamReader(stream, encode);
           string detail = reader.ReadToEnd();
           var jd = JsonConvert.DeserializeObject<WX_JSSDK>(detail);
           String access_token = (String)jd.access_token;
           #endregion
           #endregion
           #region 获取ticket
           apiurl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + access_token + "&type=jsapi";
           request = WebRequest.Create(@apiurl);
           response = request.GetResponse();
           stream = response.GetResponseStream();
           encode = Encoding.UTF8;
           reader = new StreamReader(stream, encode);
           detail = reader.ReadToEnd();
           jd = JsonConvert.DeserializeObject<WX_JSSDK>(detail);
           String ticket = jd.ticket;
           #endregion
           return ticket;
            }
            catch (Exception ex)
            {
                WeiXinHelper.WriteLog("GetTicket错误", ex.ToString());
                throw;
            }
        }
        #endregion
 
       
        /// <summary>
        /// 企业支付用户参数
        /// </summary>
        /// <returns></returns>
        public string GetPayUserParameters(string openid, decimal cost, config_WX wxConfigMolde) 
        {
            try
            {
               // wx_config wxConfigMolde = (Session["wxConfig"] as wx_config);
                Random rd = new Random();//构造随机数
                
      
                WxPayData jsApiParam = new WxPayData();
                jsApiParam.SetValue("mch_appid", wxConfigMolde.AppId);
                jsApiParam.SetValue("mchid", wxConfigMolde.mchid);
                jsApiParam.SetValue("nonce_str", WxPayApi.GenerateNonceStr());//随机字符串，不长于32位
                jsApiParam.SetValue("partner_trade_no",  DateTime.Now.ToString("yyyyMMddHHmmss").ToString());
                jsApiParam.SetValue("openid", openid);
                jsApiParam.SetValue("check_name", "NO_CHECK");//备注信息
                jsApiParam.SetValue("amount", Convert.ToInt32(cost * 100));
                jsApiParam.SetValue("desc", "上海诺标");
                jsApiParam.SetValue("spbill_create_ip", "211.149.234.224");
                jsApiParam.SetValue("sign", jsApiParam.MakeSign());//签名,切记，这个签名参数必须放在最后，因为他生成的签名，跟前面的参数有关系
                string parameters = jsApiParam.ToXml();
                return parameters;
            }
            catch (Exception ex)
            {
                Common.WeiXinHelper.WriteLog("企业支付用户err", ex.ToString());
                throw;
            }
          
        }

      


        /// <summary>
        ///关注公众号事件推送 参数格式化
        /// </summary>
        /// <returns></returns>
        public string GetPushParameters(string openid) 
        {
            try
            {
                // wx_config wxConfigMolde = (Session["wxConfig"] as wx_config);
                Random rd = new Random();//构造随机数

                string strMch_billno = WxPayConfig.MCHID + DateTime.Now.ToString("yyyyMMddHHmmss").ToString();
                WxPayData jsApiParam = new WxPayData();
                jsApiParam.SetValue("ToUserName", "gh_4c8b487a649c");//商户的公众号原始id。
                jsApiParam.SetValue("FromUserName", openid);//用户的openid。
                jsApiParam.SetValue("CreateTime", 123456789);//消息创建时间（整型）。
                jsApiParam.SetValue("MsgType", "event");//消息类型，event。
                jsApiParam.SetValue("Event", "subscribe");//事件类型，user_scan_product_enter_session为进入公众号事件。
   
                jsApiParam.SetValue("sign", jsApiParam.MakeSign());//签名,切记，这个签名参数必须放在最后，因为他生成的签名，跟前面的参数有关系
                string parameters = jsApiParam.ToXml();
                return parameters;
            }
            catch (Exception ex)
            {
                Common.WeiXinHelper.WriteLog("关注公众号事件推送err", ex.ToString());
                throw;
            }
        }



        /// <summary>
        /// 提交请求
        /// </summary>
        /// <param name="posturl"></param>
        /// <param name="postData"></param>
        /// <returns></returns>
        public string WxRedPackPost(string posturl, string postData, string CredentialAddress)
        {
            Stream outstream = null;
            Stream instream = null;
            StreamReader sr = null;
            HttpWebResponse response = null;
            HttpWebRequest request = null;
            Encoding encoding = Encoding.UTF8;
            byte[] data = encoding.GetBytes(postData);
            try
            {
                //CerPath证书路径，这里是本机的路径，实际应用中，按照实际情况来填写
                // string certPath = @"E:\FileTemp\FEIYADONG\tapp\app发布\cert\apiclient_cert.p12";
 
                //证书密码
                WeiXinHelper.WriteLog("证书地址",CredentialAddress);
                string password = WxPayConfig.SSLCERT_PASSWORD;
                X509Certificate2 cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(CredentialAddress, password, X509KeyStorageFlags.MachineKeySet);
                // 设置参数  
                request = WebRequest.Create(posturl) as HttpWebRequest;
                CookieContainer cookieContainer = new CookieContainer();
                request.CookieContainer = cookieContainer;//不可少（个人理解为，返回的时候需要验证）
                request.AllowAutoRedirect = true;
                request.Method = "POST";
                request.ContentType = "text/xml";
                request.ContentLength = data.Length;
                request.ClientCertificates.Add(cert);//添加证书请求
                outstream = request.GetRequestStream();
                outstream.Write(data, 0, data.Length);
                outstream.Close();
                //发送请求并获取相应回应数据  
                response = request.GetResponse() as HttpWebResponse;
                //直到request.GetResponse()程序才开始向目标网页发送Post请求  
                instream = response.GetResponseStream();
                sr = new StreamReader(instream, encoding);
                //返回结果网页（html）代码  
                string content = sr.ReadToEnd();
                Common.WeiXinHelper.WriteLog("发红包支付信息返回数据", content);
                string err = string.Empty;
                return content;

            }
            catch (Exception ex)
            {
                Common.WeiXinHelper.WriteLog("发红包支付信息错误！", ex.ToString());
                return ex.ToString();
            }
        }
	}
}